package com.cencat.common.utils;

import com.cencat.common.constant.CommonConstants;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期时间工具类
 */
public class DateUtils {
    
    /**
     * 获取当前时间
     * @return 当前时间
     */
    public static Date now() {
        return new Date();
    }
    
    /**
     * 获取当前时间戳（毫秒）
     * @return 时间戳
     */
    public static long currentTimeMillis() {
        return System.currentTimeMillis();
    }
    
    /**
     * 获取当前时间戳（秒）
     * @return 时间戳（秒）
     */
    public static long currentTimeSeconds() {
        return System.currentTimeMillis() / 1000;
    }
    
    /**
     * 格式化日期
     * @param date 日期
     * @param pattern 格式
     * @return 格式化后的字符串
     */
    public static String format(Date date, String pattern) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }
    
    /**
     * 格式化日期（默认格式）
     * @param date 日期
     * @return 格式化后的字符串
     */
    public static String format(Date date) {
        return format(date, CommonConstants.DATETIME_FORMAT);
    }
    
    /**
     * 解析日期字符串
     * @param dateStr 日期字符串
     * @param pattern 格式
     * @return 日期对象
     */
    public static Date parse(String dateStr, String pattern) {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new IllegalArgumentException("日期格式错误: " + dateStr, e);
        }
    }
    
    /**
     * 解析日期字符串（默认格式）
     * @param dateStr 日期字符串
     * @return 日期对象
     */
    public static Date parse(String dateStr) {
        return parse(dateStr, CommonConstants.DATETIME_FORMAT);
    }
    
    /**
     * 日期加减
     * @param date 日期
     * @param field 字段（Calendar.YEAR, Calendar.MONTH等）
     * @param amount 数量
     * @return 加减后的日期
     */
    public static Date add(Date date, int field, int amount) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(field, amount);
        return calendar.getTime();
    }
    
    /**
     * 添加天数
     * @param date 日期
     * @param days 天数
     * @return 添加后的日期
     */
    public static Date addDays(Date date, int days) {
        return add(date, Calendar.DAY_OF_MONTH, days);
    }
    
    /**
     * 添加小时
     * @param date 日期
     * @param hours 小时数
     * @return 添加后的日期
     */
    public static Date addHours(Date date, int hours) {
        return add(date, Calendar.HOUR_OF_DAY, hours);
    }
    
    /**
     * 添加分钟
     * @param date 日期
     * @param minutes 分钟数
     * @return 添加后的日期
     */
    public static Date addMinutes(Date date, int minutes) {
        return add(date, Calendar.MINUTE, minutes);
    }
    
    /**
     * 计算两个日期的天数差
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 天数差
     */
    public static long daysBetween(Date startDate, Date endDate) {
        LocalDate start = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate end = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        return Duration.between(start.atStartOfDay(), end.atStartOfDay()).toDays();
    }
    
    /**
     * 计算两个日期的小时差
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 小时差
     */
    public static long hoursBetween(Date startDate, Date endDate) {
        Instant start = startDate.toInstant();
        Instant end = endDate.toInstant();
        return Duration.between(start, end).toHours();
    }
    
    /**
     * 计算两个日期的分钟差
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 分钟差
     */
    public static long minutesBetween(Date startDate, Date endDate) {
        Instant start = startDate.toInstant();
        Instant end = endDate.toInstant();
        return Duration.between(start, end).toMinutes();
    }
    
    /**
     * 获取当天的开始时间
     * @param date 日期
     * @return 当天的开始时间
     */
    public static Date getStartOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
    
    /**
     * 获取当天的结束时间
     * @param date 日期
     * @return 当天的结束时间
     */
    public static Date getEndOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }
    
    /**
     * 获取本周的开始时间
     * @param date 日期
     * @return 本周的开始时间
     */
    public static Date getStartOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek());
        return getStartOfDay(calendar.getTime());
    }
    
    /**
     * 获取本周的结束时间
     * @param date 日期
     * @return 本周的结束时间
     */
    public static Date getEndOfWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek());
        calendar.add(Calendar.DAY_OF_WEEK, 6);
        return getEndOfDay(calendar.getTime());
    }
    
    /**
     * 获取本月的开始时间
     * @param date 日期
     * @return 本月的开始时间
     */
    public static Date getStartOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return getStartOfDay(calendar.getTime());
    }
    
    /**
     * 获取本月的结束时间
     * @param date 日期
     * @return 本月的结束时间
     */
    public static Date getEndOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return getEndOfDay(calendar.getTime());
    }
    
    /**
     * 判断日期是否在范围内
     * @param date 日期
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 是否在范围内
     */
    public static boolean isBetween(Date date, Date startDate, Date endDate) {
        if (date == null || startDate == null || endDate == null) {
            return false;
        }
        return !date.before(startDate) && !date.after(endDate);
    }
    
    /**
     * 判断日期是否在今天
     * @param date 日期
     * @return 是否在今天
     */
    public static boolean isToday(Date date) {
        if (date == null) {
            return false;
        }
        Date today = new Date();
        return format(date, CommonConstants.DATE_FORMAT)
                .equals(format(today, CommonConstants.DATE_FORMAT));
    }
    
    /**
     * 判断日期是否在昨天
     * @param date 日期
     * @return 是否在昨天
     */
    public static boolean isYesterday(Date date) {
        if (date == null) {
            return false;
        }
        Date yesterday = addDays(new Date(), -1);
        return format(date, CommonConstants.DATE_FORMAT)
                .equals(format(yesterday, CommonConstants.DATE_FORMAT));
    }
    
    /**
     * 判断日期是否在明天
     * @param date 日期
     * @return 是否在明天
     */
    public static boolean isTomorrow(Date date) {
        if (date == null) {
            return false;
        }
        Date tomorrow = addDays(new Date(), 1);
        return format(date, CommonConstants.DATE_FORMAT)
                .equals(format(tomorrow, CommonConstants.DATE_FORMAT));
    }
    
    /**
     * 获取年龄
     * @param birthDate 出生日期
     * @return 年龄
     */
    public static int getAge(Date birthDate) {
        if (birthDate == null) {
            return 0;
        }
        
        Calendar birth = Calendar.getInstance();
        birth.setTime(birthDate);
        Calendar now = Calendar.getInstance();
        
        int age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
        if (now.get(Calendar.MONTH) < birth.get(Calendar.MONTH) ||
            (now.get(Calendar.MONTH) == birth.get(Calendar.MONTH) && 
             now.get(Calendar.DAY_OF_MONTH) < birth.get(Calendar.DAY_OF_MONTH))) {
            age--;
        }
        return age;
    }
    
    /**
     * 时间戳转日期
     * @param timestamp 时间戳（毫秒）
     * @return 日期
     */
    public static Date timestampToDate(long timestamp) {
        return new Date(timestamp);
    }
    
    /**
     * 日期转时间戳
     * @param date 日期
     * @return 时间戳（毫秒）
     */
    public static long dateToTimestamp(Date date) {
        return date.getTime();
    }
}